package com.itcoon.cloud.framework.transform.assemble.handler;


import com.itcoon.cloud.framework.transform.assemble.handler.clazz.AssembleForTargetClassHandler;
import com.itcoon.cloud.framework.transform.assemble.handler.parameterized.ParameterizedTargetTypeHandler;
import com.itcoon.cloud.framework.transform.assemble.converter.AssembleConverterComposite;
import com.itcoon.cloud.framework.transform.definition.InjectDefinition;
import com.itcoon.cloud.framework.transform.exception.AssembleException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

public class AssembleHandlerComposite {

    private static final Logger log = LoggerFactory.getLogger(AssembleHandlerComposite.class);

    @Autowired
    private List<AssembleForTargetClassHandler> clazzHandlers;

    @Autowired
    private List<ParameterizedTargetTypeHandler> parameterizedTypeHandlers;

    @Autowired
    private AssembleConverterComposite assembleConverterComposite;

    public Object handle(Type targetPropertyType, Object originGetterValue, String[] ignoreProperties, List<InjectDefinition> injectInfos) {
        try{
            AssembleConverterComposite.ConvertResult convertResult = assembleConverterComposite.convert(targetPropertyType, originGetterValue);
            if(convertResult.getConverted()){
                return convertResult.getConvertValue();
            }
            if (targetPropertyType instanceof Class) {
                for (AssembleForTargetClassHandler handler : clazzHandlers) {
                    if (handler.support((Class<?>) targetPropertyType, originGetterValue, injectInfos)) {
                        return handler.handle((Class<?>) targetPropertyType, originGetterValue, ignoreProperties, injectInfos);
                    }
                }
            }
            if (targetPropertyType instanceof ParameterizedType) {
                for (ParameterizedTargetTypeHandler handler : parameterizedTypeHandlers) {
                    if (handler.support((ParameterizedType) targetPropertyType, originGetterValue, injectInfos)) {
                        return handler.handle((ParameterizedType) targetPropertyType, originGetterValue, ignoreProperties, injectInfos);
                    }
                }
            }
        }catch (Exception e){
            log.error(e.getMessage(), e);
            log.error("[Transform4j] - method assemble failure, it handle #{} to type #{}, the reason is {}",originGetterValue, targetPropertyType, e.getMessage());
            throw new AssembleException(e.getMessage());
        }
        return originGetterValue;
    }
}
